# -*- coding: utf-8 -*-
module Alignment
  def best_alignment e, f, v
    f.collect { |fi|
      best_word_id = nil
      best_perplexity = Perplexity.inf
      e.each { |ej|
        next unless v.perplexity(fi, ej) > best_perplexity
        best_word_id = e.index ej
        best_perplexity = v.perplexity fi, ej
      }
      best_word_id
    }
  end

  def test_best_alignment
    test_v = Vocabluary.new [:x, :y], [:b, :c]
    test_v.set_perplexity :x, :b, Perplexity.to_perpelx_val(1.0/2.0)
    test_v.set_perplexity :y, :b, Perplexity.to_perpelx_val(3.0/2.0)
    test_v.set_perplexity :x, :c, Perplexity.to_perpelx_val(1.0/2.0)
    test_v.set_perplexity :y, :c, Perplexity.to_perpelx_val(1.0/2.0)
    test_v.normalize

    return if best_alignment([:x, :y], [:b, :c], test_v) == [1, 0]
    raise "best_alignment fail"
  end

  def summ_prod e, f, v
    prod = Perplexity.from_i 1
    (0..f.size-1).each { |f_id|
      fi = f[f_id]
      summ = Perplexity.inf
      (0..e.size-1).each { |e_id|
        ej = e[e_id]
        summ = summ + v.perplexity(ej, fi)
      }
      prod *= summ
    }
    prod
  end

  def model1_iter txt, v, verbose = false
    new_v = Vocabluary.new v.e, v.f, Perplexity.inf.val
    txt.each { |e, f|
      e = e.uniq
      f = f.uniq
      puts "sentence "+e.size.to_s+"x"+f.size.to_s if verbose
      (0..f.size-1).each { |f_id|
        f_clone = f.clone
        fi = f_clone.delete_at f_id
        with = summ_prod(e, f, v)
        summ = Perplexity.from_i 0
        (0..e.size-1).each { |e_id|
          ej = e[e_id]
          out = v.perplexity(ej, fi) * summ_prod(e, f_clone, v)
          d = out / with
          summ += d
          new_v.add_perplexity(ej, fi, d)
        }
      }
    }
    new_v.normalize
  end

  def primitive_iteration_test
    v = Vocabluary.new([:x, :y], [:b, :c])
    (1..5).each {
      v = model1_iter([[[:x, :y], [:b, :c]],
                       [[:y], [:b]]], v)
    }

    return if best_alignment([:b, :c], [:x, :y], v) == [1, 0]
    raise "iterating failed"
  end

  def better_test
    e = [[:the, :cat, :is, :black],
         [:the, :cat, :hates, :dog],
         [:the, :dog, :is, :black],
         [:cat, :and, :dog, :hates, :other]]
    f = [[:кот, :черный],
         [:кот, :не, :любит, :собак],
         [:собак, :черный],
         [:кот, :и, :собак, :не, :любит, :другого]]
    text = f.zip e

    v = Vocabluary.new(f.flatten.uniq, e.flatten.uniq)
    (1..5).each {
      v = model1_iter(text, v)
    }

    v.print_n_best 3

    puts best_alignment([:the, :dog, :hates, :cat], [:собак, :не, :любит, :кот], v)
  end
end

